package com.xmtlxx.web.controller.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.xmtlxx.system.mapper.SysDeptMapper;
import com.xmtlxx.web.controller.wms.service.IViewingService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xmtlxx.common.core.domain.PageQuery;
import com.xmtlxx.common.core.page.TableDataInfo;
import com.xmtlxx.common.helper.LoginHelper;
import com.xmtlxx.common.sms.aliyun.AliyunSmsService;
import com.xmtlxx.common.sms.aliyun.SmsRequest;
import com.xmtlxx.common.sms.aliyun.SmsTemplateCode;
import com.xmtlxx.common.sms.aliyun.SmsTemplateParam;
import com.xmtlxx.common.utils.DateUtils;
import com.xmtlxx.common.utils.StringUtils;
import com.xmtlxx.system.domain.SysOss;
import com.xmtlxx.system.domain.bo.SysOssBo;
import com.xmtlxx.system.mapper.SysOssMapper;
import com.xmtlxx.system.mapper.SysUserMapper;
import com.xmtlxx.wms.domain.Viewing;
import com.xmtlxx.wms.domain.ViewingDtl;
import com.xmtlxx.wms.domain.ViewingPerson;
import com.xmtlxx.wms.domain.bo.ViewingBo;
import com.xmtlxx.wms.domain.bo.ViewingDtlBo;
import com.xmtlxx.wms.domain.vo.*;
import com.xmtlxx.wms.mapper.*;
import com.xmtlxx.wms.domain.vo.InventoryVo;
import com.xmtlxx.wms.domain.vo.StoreVo;
import com.xmtlxx.wms.domain.vo.ViewingDtlVo;
import com.xmtlxx.wms.domain.vo.ViewingVo;
import com.xmtlxx.wms.mapper.InventoryMapper;
import com.xmtlxx.wms.mapper.StoreMapper;
import com.xmtlxx.wms.mapper.ViewingDtlMapper;
import com.xmtlxx.wms.mapper.ViewingMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 看样记录Service业务层处理
 *
 * @author xmtlxx
 * @date 2022-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ViewingServiceImpl implements IViewingService {

    private final ViewingMapper baseMapper;

    private final ViewingDtlMapper viewingDtlMapper;

    private final ViewingPersonMapper viewingPersonMapper;

    private final SysOssMapper sysOssMapper;

    private final StoreMapper storeMapper;

    private final SysUserMapper userMapper;

    private final InventoryMapper inventoryMapper;

    private final SysDeptMapper deptMapper;

    private final AliyunSmsService aliyunSmsService;

    /**
     * 查询看样记录
     *
     * @param id 看样记录主键
     * @return 看样记录
     */
    @Override
    public ViewingVo queryById(String id){
        //return baseMapper.selectVoById(id);
        return baseMapper.selectViewingVoByID(id);
    }

    /**
     * 查询看样记录列表
     *
     * @param bo 看样记录
     * @return 看样记录
     */
    @Override
    public TableDataInfo<ViewingVo> queryPageList(ViewingBo bo, PageQuery pageQuery) {
       // LambdaQueryWrapper<Viewing> lqw = buildQueryWrapper(bo);
       // Page<ViewingVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-DD-mm");
        Page<ViewingVo> result = baseMapper.selectPageViewingList(pageQuery.build(), bo);
        if(result != null && result.getRecords() != null && result.getRecords().size() > 0){
            for (ViewingVo vo:result.getRecords()){
                if(vo.getApplyDay() != null){
                    vo.setApplyDayNew(format.format(vo.getApplyDay()));
                }
                //获取物品名称
                String propertyNames = "";
                ViewingDtlBo dtlBo = new ViewingDtlBo();
                dtlBo.setViewingId(vo.getId());
                List<ViewingDtlVo> dtlVos = viewingDtlMapper.selectViewingDtlList(dtlBo);
                if(dtlVos != null && dtlVos.size() > 0){
                    propertyNames = dtlVos.stream().map(ViewingDtlVo::getName).collect(Collectors.joining("|"));
                }
                vo.setPropertyNames(propertyNames);
                List<ViewingPersonVo> persons = viewingPersonMapper.selectViewPersonListByViewId(vo.getId());
                if(persons != null && persons.size() != 0){
                    vo.setName(persons.get(0).getName());
                    vo.setTel(persons.get(0).getTel());
                    vo.setIdCard(persons.get(0).getIdCard());
                }
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询看样记录列表
     *
     * @param bo 看样记录
     * @return 看样记录
     */
    @Override
    public List<ViewingVo> queryList(ViewingBo bo) {
       // LambdaQueryWrapper<Viewing> lqw = buildQueryWrapper(bo);
       // return baseMapper.selectVoList(lqw);
        return baseMapper.selectViewingList(bo);
    }

    private LambdaQueryWrapper<Viewing> buildQueryWrapper(ViewingBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Viewing> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getViewingNo()), Viewing::getViewingNo, bo.getViewingNo());
        lqw.eq(bo.getDeptId() != null, Viewing::getDeptId, bo.getDeptId());
        lqw.eq(bo.getOperator() != null, Viewing::getOperator, bo.getOperator());
        lqw.between(params.get("beginApplyDay") != null && params.get("endApplyDay") != null,
            Viewing::getApplyDay ,params.get("beginApplyDay"), params.get("endApplyDay"));
        lqw.eq(StringUtils.isNotBlank(bo.getStoreId()), Viewing::getStoreId, bo.getStoreId());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Viewing::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), Viewing::getCreateBy, bo.getCreateBy());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            Viewing::getCreateTime ,params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), Viewing::getUpdateBy, bo.getUpdateBy());
        lqw.between(params.get("beginUpdateTime") != null && params.get("endUpdateTime") != null,
            Viewing::getUpdateTime ,params.get("beginUpdateTime"), params.get("endUpdateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), Viewing::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    /**
     * 新增看样记录
     *
     * @param bo 看样记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(ViewingBo bo) {
        Viewing add = BeanUtil.toBean(bo, Viewing.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setViewingNo(getNo());
        add.setDelFlag("0");
        add.setStatus("0");
        add.setDeptId(LoginHelper.getDeptId());
        add.setType("0");
        add.setCheckStatus("0");

        List<ViewingPerson> persons = new ArrayList<>();
        if(bo.getPersonData() != null && bo.getPersonData().size() > 0){
            for(ViewingPersonVo item : bo.getPersonData()){
                ViewingPerson person = BeanUtil.toBean(item, ViewingPerson.class);
                person.setId(IdUtil.simpleUUID());
                person.setViewingId(add.getId());
                person.setDelFlag("0");
                persons.add(person);
            }
        }

        List<ViewingDtl> dtls = new ArrayList<>();
        if(bo.getItems() != null && bo.getItems().size() > 0){
            for (ViewingDtlVo item : bo.getItems()){
                ViewingDtl dtl = BeanUtil.toBean(item, ViewingDtl.class);
                dtl.setId(IdUtil.simpleUUID());
                dtl.setViewingId(add.getId());
                dtl.setDelFlag("0");
                dtl.setStatus("0");
                dtl.setViewTime(new Date());
                dtls.add(dtl);
            }
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }

        if(dtls != null && dtls.size() > 0){
            viewingDtlMapper.insertBatch(dtls);
        }
        if(persons != null && persons.size() > 0){
            viewingPersonMapper.insertBatch(persons);
        }
        if(bo.getOss() != null && bo.getOss().size() > 0){
            for(SysOss oss : bo.getOss()){
                oss.setBuss("viewing");
                oss.setObjid(add.getId());
                sysOssMapper.updateById(oss);
            }
        }

        if(flag){
            StoreVo storeVo = storeMapper.selectVoById(add.getStoreId());
            if(storeVo != null){
                SmsRequest smsRequest = new SmsRequest();
                smsRequest.setTemplateCode(SmsTemplateCode.VIEWING_NOTICE.getSMS_CODE());
                smsRequest.setPhoneNumber(userMapper.selectUserById(storeVo.getUserId()).getPhonenumber());
                SmsTemplateParam templateParam = new SmsTemplateParam();
                smsRequest.setTemplateParam(templateParam);
                templateParam.setArea(deptMapper.getAreaName(bo.getDeptId()));
                aliyunSmsService.AliyunSmsSend(smsRequest);
            }
        }


        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByReceive(ViewingBo bo) {
        Viewing add = BeanUtil.toBean(bo, Viewing.class);
        validEntityBeforeSave(add);
        boolean flag = false;
        add.setId(IdUtil.simpleUUID());
        add.setStatus("0");
        add.setDelFlag("0");
        add.setCheckStatus("1");
        add.setViewingNo(getNo());
        add.setType("1");

        if(bo.getItems() != null && bo.getItems().size() > 0){
            List<ViewingDtl> dtls = bo.getItems().stream().map(item->{
                ViewingDtl dtl = BeanUtil.toBean(item,ViewingDtl.class);
                dtl.setId(IdUtil.simpleUUID());
                dtl.setViewingId(add.getId());
                dtl.setDelFlag("0");
                dtl.setStatus("0");
                InventoryVo inventoryVo = inventoryMapper.selectInventoryVoByPno(item.getPno());
                if(inventoryVo != null){
                    dtl.setNums(inventoryVo.getNums());
                    add.setStoreId(inventoryVo.getStoreId());
                }
                dtl.setViewTime(new Date());
                return dtl;
            }).collect(Collectors.toList());
            flag = viewingDtlMapper.insertBatch(dtls);
        }
        flag = baseMapper.insert(add) > 0;
        return flag;
    }

    @Override
    public List<ViewingVo> getViewingVos() {
        ViewingBo bo = new ViewingBo();
        bo.setType("1");
        List<ViewingVo> vos = baseMapper.selectViewingList(bo);
        if(vos != null && vos.size() > 0){
            vos.stream().forEach(item->{
                ViewingDtlBo dtlBo = new ViewingDtlBo();
                dtlBo.setViewingId(item.getId());
                List<ViewingDtlVo> dtlVos = viewingDtlMapper.selectViewingDtlList(dtlBo);
                item.setItems(dtlVos);

                /**
                 * 附件信息
                 */
                SysOssBo ossBo = new SysOssBo();
                ossBo.setObjid(item.getId());
                ossBo.setBuss("remote");
                List<SysOss> oss = sysOssMapper.selectSysOssList(ossBo);
                item.setOss(oss);
            });
        }
        return vos;
    }

    /**
     * 修改看样记录
     *
     * @param bo 看样记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(ViewingBo bo) {
        Viewing update = BeanUtil.toBean(bo, Viewing.class);
        validEntityBeforeSave(update);

        /**
         * 已审核
         */
        if(!update.getCheckStatus().equals("0")){
            update.setChecker(LoginHelper.getNickname());
            update.setCheckTime(new Date());
        }
        /**
         * 审核不通过，编辑后可重新审核
         * 重新审核标签 update
         */
        if(update.getCheckStatus().equals("2") && StringUtils.isNotEmpty(bo.getSubmitType()) && bo.getSubmitType().equals("update")){
            update.setCheckStatus("0");//重新审核
        }

        /**
         * 查询原明细数据
         */
        ViewingDtlBo dtlBo = new ViewingDtlBo();
        dtlBo.setViewingId(update.getId());
        List<ViewingDtlVo> olds = viewingDtlMapper.selectViewingDtlList(dtlBo);
        List<ViewingPersonVo> personOlds = viewingPersonMapper.selectViewPersonListByViewId(update.getId());

        List<ViewingDtl> dtls = new ArrayList<>();
        if(bo.getItems() != null && bo.getItems().size() > 0){
            dtls = bo.getItems().stream().map(item->{
                ViewingDtl dtl = new ViewingDtl();
                BeanUtil.copyProperties(item,dtl);
                if(StringUtils.isEmpty(dtl.getId())){//修改后的物品
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setDelFlag("0");
                    dtl.setStatus("0");
                    dtl.setViewingId(update.getId());
                }
                /**
                 * 迭代查询移除的明细
                 */
                Iterator iterator = olds.iterator();
                while(iterator.hasNext()){
                    ViewingDtlVo viewingDtlVo = (ViewingDtlVo) iterator.next();
                    if(viewingDtlVo.getId().equals(dtl.getId())){
                        iterator.remove();
                    }
                }

                /**
                 * type 0-阅证申请，1-远程示证
                 */
                if(update.getType().equals("1")){
                    if(item.getOss() != null && item.getOss().size() > 0){
                        for(SysOss oss : item.getOss()){
                            oss.setBuss("remote");
                            oss.setObjid(item.getId());
                            sysOssMapper.updateById(oss);
                        }
                    }
                }

                return dtl;
            }).collect(Collectors.toList());

        }

        List<ViewingPerson> persons = new ArrayList<>();
        if(bo.getPersonData() != null && bo.getPersonData().size() > 0){
            persons = bo.getPersonData().stream().map(item->{
                ViewingPerson person = new ViewingPerson();
                BeanUtil.copyProperties(item,person);
                if(StringUtils.isEmpty(person.getId())){//修改后的物品
                    person.setId(IdUtil.simpleUUID());
                    person.setDelFlag("0");
                    person.setViewingId(update.getId());
                }
                /**
                 * 迭代查询移除的明细
                 */
                Iterator iterator = personOlds.iterator();
                while(iterator.hasNext()){
                    ViewingPersonVo viewingPersonVo = (ViewingPersonVo) iterator.next();
                    if(viewingPersonVo.getId().equals(person.getId())){
                        iterator.remove();
                    }
                }


                return person;
            }).collect(Collectors.toList());

        }

        if(dtls.size() > 0){
            viewingDtlMapper.insertOrUpdateBatch(dtls);
        }
        if(persons.size() > 0){
            viewingPersonMapper.insertOrUpdateBatch(persons);
        }
        //已删除的物品处理：删除dtl表、回退可移交状态
        if(bo.getItems() != null && bo.getItems().size() > 0 && olds != null && olds.size() > 0){
            olds.forEach(item -> {
                viewingDtlMapper.deleteById(item.getId());
            });
        }
        if(bo.getPersonData() != null && bo.getPersonData().size() > 0 && personOlds != null && personOlds.size() > 0){
            personOlds.forEach(item -> {
                viewingPersonMapper.deleteById(item.getId());
            });
        }

        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateViewingByBo(ViewingBo bo) {

        Viewing update = BeanUtil.toBean(bo, Viewing.class);
        validEntityBeforeSave(update);

        if(bo.getOss() != null && bo.getOss().size() > 0){
            for(SysOss oss : bo.getOss()){
                oss.setBuss("viewing");
                oss.setObjid(update.getId());
                sysOssMapper.updateById(oss);
            }
        }

        if(bo.getItemsOss() != null && bo.getItemsOss().size() > 0){
            for(SysOss oss : bo.getItemsOss()){
                oss.setBuss("viewingDtl");
                oss.setObjid(update.getId());
                sysOssMapper.updateById(oss);
            }
        }

        if(StringUtils.isNotEmpty(bo.getCenterOssId())){
            SysOss oss = sysOssMapper.selectById(bo.getCenterOssId());
            oss.setBuss("viewingCenter");
            oss.setObjid(update.getId());
            sysOssMapper.updateById(oss);
        }
        if(StringUtils.isNotEmpty(bo.getSignOssId())){
            SysOss oss = sysOssMapper.selectById(bo.getSignOssId());
            oss.setBuss("viewingSign");
            oss.setObjid(update.getId());
            sysOssMapper.updateById(oss);
        }

        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateViewingByEnty(ViewingBo bo) {
        Viewing update = BeanUtil.toBean(bo, Viewing.class);
        validEntityBeforeSave(update);

        /**
         * 已审核
         */
        if(!update.getCheckStatus().equals("0")){
            update.setChecker(LoginHelper.getNickname());
            update.setCheckTime(new Date());
        }

        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Viewing entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除看样记录
     *
     * @param ids 需要删除的看样记录主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    public String getNo(){
        LambdaQueryWrapper<Viewing> lqw = Wrappers.lambdaQuery();
        Long maxNumObject = baseMapper.selectCount(lqw);
        String num = "";
        String todayStr = DateUtils.date2String(new Date(), "yyMMdd");

        if (maxNumObject == null) {
            num = todayStr + "000001";
        } else {
            String maxnumStr = "00000" + maxNumObject.toString();
            String maxnumNo = maxnumStr.substring(maxnumStr.length() - 6, maxnumStr.length());
            String nextnumNo = StringUtils.nextNo(maxnumNo, 6);
            num = todayStr + nextnumNo;
        }
        return num;
    }
}
